Skip to content

Feat/at reference#3560

Merged
TheodoreSpeaks merged 6 commits intofeat/mothership-copilotfrom
feat/at-reference
Mar 13, 2026
Merged

Feat/at reference#3560
TheodoreSpeaks merged 6 commits intofeat/mothership-copilotfrom
feat/at-reference

Conversation

@TheodoreSpeaks
Copy link
Collaborator

Summary

Added @ing resources to reference them and insert it into context
Fixes #(issue)

Type of Change

  • Bug fix
  • New feature
  • Breaking change
  • Documentation
  • Other: ___________

Testing

Validated context is passed. Resource menu also updated and block colors persisted.

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

Screenshots/Videos

@vercel
Copy link

vercel bot commented Mar 13, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Skipped Skipped Mar 13, 2026 8:30am

Request Review

@cursor
Copy link

cursor bot commented Mar 13, 2026

PR Summary

Medium Risk
Moderate risk because it changes chat input behavior and request payloads/persistence to include new contexts data (including new table/file kinds), which could affect message submission, storage, and context processing end-to-end.

Overview
Enables @-mentioning workspace resources (workflows, knowledgebases, tables, files) in the Home chat input, automatically adding them as message contexts and displaying removable context pills.

Propagates contexts through the full chat flow: client sendMessage/UI state, task history types, and POST /api/mothership/chat persistence + server-side context processing (including new table/file resolvers). User message rendering now highlights mentioned tokens based on attached contexts, and resource additions are persisted when a chat ID exists.

Written by Cursor Bugbot for commit d5ba7c4. This will update automatically on new commits. Configure here.

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Mar 13, 2026

Greptile Summary

This PR adds @mention-based resource referencing to the home chat interface, allowing users to type @ to pick workflows, knowledge bases, tables, or files and insert them as context that is forwarded to the Mothership API alongside the message.

Key changes:

  • user-input.tsx: Adds a highlight overlay (text-transparent textarea + absolutely-positioned mirrored div), a resource mention menu (Popover portal), context pill display, and a redesigned + button that exposes both file attachments and a resource submenu. Keyboard navigation for mention selection and mention-token skipping is handled inline.
  • user-message-content.tsx: New component that re-renders stored user messages with @mention tokens highlighted using the workflow's color (or green fallback).
  • context-pills.tsx: New badge row displaying selected contexts with per-kind icons and individual remove buttons.
  • use-chat.ts: Extends sendMessage to pass contexts to the API and maps stored contexts back on chat history load. Also adds fire-and-forget resource persistence to /api/copilot/chat/resources.
  • API route: Adds contexts to the stored message payload with Zod validation.
  • use-mention-menu.ts: Minor fix removing a duplicate trailing space from @mention insertion.

Notable concerns:

  • table and file resource types are mapped to kind: 'docs' with no ID, so the backend cannot resolve their content — only the label is forwarded.
  • user-input.tsx imports shared hooks and utilities directly from the deeply nested copilot panel feature path, creating tight cross-feature coupling.
  • Unused cn import in user-message-content.tsx.
  • Dead condition e.key === 'Space' in the keyboard handler (harmless but misleading).

Confidence Score: 3/5

  • Functional for workflow and knowledge-base references; table/file mentions silently lose their IDs and the home feature is now tightly coupled to copilot panel internals.
  • The core @mention flow for workflows and knowledge bases is well-implemented and properly wired end-to-end. However, table and file resource types lose their IDs during context mapping, meaning the backend cannot act on those references — a logic gap that may surface when those resource types are used. Additionally, importing internal copilot hooks directly into the home feature creates a fragile cross-feature dependency. These issues lower confidence from an otherwise solid implementation.
  • apps/sim/app/workspace/[workspaceId]/home/components/user-input/user-input.tsx — resource ID loss in mapResourceToContext and cross-feature import coupling.

Important Files Changed

Filename Overview
apps/sim/app/workspace/[workspaceId]/home/components/user-input/user-input.tsx Major new feature: adds @mention resource picker, highlight overlay, context pill management, and a redesigned + menu. Contains dead code (e.key === 'Space'), table/file resource IDs being silently dropped in context mapping, and deep cross-feature imports from the copilot panel hooks.
apps/sim/app/workspace/[workspaceId]/home/components/user-message-content.tsx New component for rendering user messages with @mention highlights. Has an unused cn import. The mention-range regex correctly handles start/end-of-string but silently misses mentions followed by non-whitespace punctuation.
apps/sim/app/workspace/[workspaceId]/home/hooks/use-chat.ts Extends sendMessage to accept and forward contexts to the API, maps stored message contexts on load, and adds a fire-and-forget resource persistence call to /api/copilot/chat/resources. Clean implementation.
apps/sim/app/api/mothership/chat/route.ts Adds contexts array to the stored message payload, mapping only kind, label, workflowId, and knowledgeId. Straightforward and consistent with the existing schema.
apps/sim/app/workspace/[workspaceId]/home/components/user-input/components/context-pills.tsx New component rendering dismissible context badges with appropriate icons per context kind. current_workflow contexts are correctly filtered out of the visible pill list.
apps/sim/app/workspace/[workspaceId]/home/home.tsx Wires up onContextAdd callback and contexts through the submit chain. Replaces inline paragraph rendering with the new UserMessageContent component. Clean changes.
apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/user-input/hooks/use-mention-menu.ts Minor fix: removes a duplicate trailing space from the @mention insertion string (double space → single space). Correct and intentional.
apps/sim/hooks/queries/tasks.ts Adds TaskStoredMessageContext interface and contexts field to TaskStoredMessage. Minimal, clean addition.

Sequence Diagram

sequenceDiagram
    actor User
    participant UI as UserInput
    participant MM as ResourceMentionMenu
    participant CM as useContextManagement
    participant HC as useChat (sendMessage)
    participant API as /api/mothership/chat

    User->>UI: Types @resource or clicks + Resources
    UI->>MM: Show mention menu (portal to body)
    User->>MM: Selects a resource
    MM->>UI: onSelect(resource, fromMentionMenu)
    UI->>UI: mapResourceToContext(resource)
    UI->>CM: addContext(context)
    CM-->>UI: selectedContexts updated
    UI->>UI: Render ContextPills + highlight overlay

    User->>UI: Submits message
    UI->>HC: onSubmit(text, fileAttachments, contexts)
    HC->>HC: Build userMessage with contexts
    HC->>HC: setMessages([...prev, userMessage])
    HC->>API: POST { message, contexts, fileAttachments, ... }
    API->>API: Validate with Zod schema
    API->>API: Store contexts in DB (copilotChats)
    API-->>HC: SSE stream response
    HC-->>UI: isSending = false, messages updated
    UI->>UI: Render UserMessageContent with mention highlights
Loading

Comments Outside Diff (1)

  1. apps/sim/app/workspace/[workspaceId]/home/components/user-input/user-input.tsx, line 893 (link)

    Dead condition: e.key === 'Space' is always false

    e.key for the space bar is ' ' (a single space character), not the string 'Space' (that would be e.code). The condition e.key === 'Space' is therefore always false. It is harmless here because e.key.length === 1 already catches the space bar (since ' '.length === 1), but the || e.key === 'Space' branch is dead code and should be removed to avoid confusion.

Last reviewed commit: 16ccf74

Comment on lines +3 to +5
import { cn } from '@/lib/core/utils/cn'
import type { ChatMessageContext } from '../types'
import { useWorkflowRegistry } from '@/stores/workflows/registry/store'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused cn import

cn is imported on line 3 but is never referenced anywhere in this file. This will likely trigger a lint warning. It should be removed.

Suggested change
import { cn } from '@/lib/core/utils/cn'
import type { ChatMessageContext } from '../types'
import { useWorkflowRegistry } from '@/stores/workflows/registry/store'
import type { ChatMessageContext } from '../types'
import { useWorkflowRegistry } from '@/stores/workflows/registry/store'

Comment on lines +236 to +241
style={{
position: 'fixed',
top: `${caretViewport.top}px`,
left: `${caretViewport.left}px`,
width: '1px',
height: '1px',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

table and file resource IDs are dropped silently

For the table and file resource types, the resource's id is not included in the returned context object. The API schema also has no tableId/fileId field, so the backend receives only a label string for these resources — it cannot resolve or retrieve the actual content of the referenced table or file. If these resource types are intended to be actionable in context (not just decorative labels), either a new ID field needs to be added to the schema or these types should be excluded from the @mention resource list.

case 'table':
  return { kind: 'docs', label: resource.title }
  // resource.id is silently dropped — backend has no way to look up this table
case 'file':
  return { kind: 'docs', label: resource.title }
  // same issue for file

Comment on lines +182 to +191
.filter((item) => item.name.toLowerCase().includes(searchQuery))
.map((item) => ({ type, item }))
)
}
// When no query, show all items flat
return availableResources.flatMap(({ type, items }) =>
items.map((item) => ({ type, item }))
)
}, [availableResources, query])

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Deep cross-feature import coupling

user-input.tsx in the home feature directly imports implementation hooks and utilities from the deeply nested copilot panel feature path:

@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/user-input/hooks
@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/user-input/utils

This creates a tight coupling between two unrelated features. If the copilot panel's internal structure changes, the home feature breaks. Consider extracting the shared hooks (useCaretViewport, useContextManagement, useMentionMenu, useMentionTokens) and utilities into a shared location (e.g., @/hooks/ or @/lib/), following the established path alias patterns in the project.

Rule Used: Use established path alias patterns instead of dee... (source)

Learnt From
simstudioai/sim#233


document.addEventListener('keydown', handleKeyDown)
return () => document.removeEventListener('keydown', handleKeyDown)
}, [flatItems, activeIndex, handleSelect, onClose])
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Enter key blocked when mention menu has no results

Medium Severity

The ResourceMentionMenu registers a global document keydown listener that intercepts Enter/Tab and calls e.preventDefault(). Simultaneously, the textarea's handleKeyDown also intercepts Enter and prevents default when showMentionMenu is true. When the mention menu is visible but shows "No results", pressing Enter does nothing — the message cannot be submitted because both handlers block it. The user must press Escape first.

Additional Locations (1)
Fix in Cursor Fix in Web

@TheodoreSpeaks TheodoreSpeaks merged commit 8dbdebd into feat/mothership-copilot Mar 13, 2026
4 checks passed
@TheodoreSpeaks TheodoreSpeaks deleted the feat/at-reference branch March 13, 2026 08:32
Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 3 potential issues.

There are 4 total unresolved issues (including 1 from previous review).

Fix All in Cursor

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

const tokenEnd = tokenStart + token.length
ranges.push({ start: tokenStart, end: tokenEnd, token, context: ctx })
}
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mention regex fails for tokens at text boundaries

Medium Severity

The computeMentionRanges regex pattern (^|\s)(@label)(\s|$) requires the mention token to be followed by whitespace or end-of-string. This means a mention at the end of the message text (which is common — users type @WorkflowName and hit send) will only match if there's a trailing space. Since the message is trimmed before sending (text.trim() in handleSubmit), trailing spaces are removed, so mentions at the very end of the user's message won't be highlighted in the rendered chat history.

Fix in Cursor Fix in Web

const tokenStart = match.index + leadingSpace.length
const tokenEnd = tokenStart + token.length
ranges.push({ start: tokenStart, end: tokenEnd, token, context: ctx })
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adjacent mentions missed due to regex consuming shared whitespace

Medium Severity

In computeMentionRanges, the regex pattern (^|\s)(@label)(\s|$) with the g flag consumes the trailing whitespace as part of the match. When two mentions are separated by a single space (e.g., @Workflow1 @Workflow2), the space is consumed by the first match's (\s|$) group, so the second mention's required (^|\s) prefix can't match — the second mention is silently skipped and won't be highlighted in the rendered message.

Fix in Cursor Fix in Web

const tokenEnd = tokenStart + token.length
ranges.push({ start: tokenStart, end: tokenEnd, token, context: ctx })
}
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adjacent mention tokens miss highlighting due to whitespace consumption

Low Severity

In computeMentionRanges, the regex (^|\s)(@label)(\s|$) with the g flag consumes trailing whitespace as part of the match. When the same label appears twice separated by a single space, the first match consumes the space, causing the regex's lastIndex to skip past the second occurrence's required leading whitespace — the second mention won't be highlighted. Using a lookahead (?=\s|$) instead of (\s|$) would avoid consuming the boundary character.

Fix in Cursor Fix in Web

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant